package com.zmn.oms.zmn.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.base.engineer.common.dro.basic.EngineerCooperateInfoDRO;
import com.zmn.base.engineer.common.dro.basic.EngineerServSkillDRO;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.common.enums.EngineerOAStatusEnum;
import com.zmn.base.engineer.dubbo.interfaces.engineer.cooperate.EngineerCooperateInfoListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.engineer.servskill.EngineerServSkillListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.biz.engineer.common.dro.distribute.EngineerTakeConfigDRO;
import com.zmn.biz.engineer.dubbo.interfaces.distribute.EngineerTakeConfigListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.gms.common.dio.grid.edit.engineer.EngineerGridDRO;
import com.zmn.gms.dubbo.interfaces.grid.edit.engineer.GridEditEngineerListRemoteService;
import com.zmn.manager.common.utils.BaiduMapUtil;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.manager.redis.RedisManager;
import com.zmn.manager.redis.lock.DistributedLock;
import com.zmn.manager.redis.lock.DistributedLockUtils;
import com.zmn.oms.business.interfaces.baidumap.BaiduMapBService;
import com.zmn.oms.business.interfaces.conf.distribute.DistributeWeightListBService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.graborder.GrabOrderBService;
import com.zmn.oms.business.interfaces.work.OrderWorkBService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.normal.query.GrabQueryDIO;
import com.zmn.oms.common.dro.conf.distribute.*;
import com.zmn.oms.common.dro.normal.master.NonGridGrabOrderDRO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.DateTimeUtil;
import com.zmn.oms.common.utils.DesensitizeUtil;
import com.zmn.oms.constant.MessageQueueTopicConstant;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.dto.graborder.GrabConfigDTO;
import com.zmn.oms.model.dto.graborder.GrabOrderDTO;
import com.zmn.oms.model.dto.graborder.GrabOrderWorkDTO;
import com.zmn.oms.model.dto.graborder.GrabWorkQuery;
import com.zmn.oms.model.dto.work.masterwork.MasterTakeDTO;
import com.zmn.oms.model.dto.work.modify.OrderDistributeDTO;
import com.zmn.oms.model.dto.work.modify.must.OrderWorkGrabDTO;
import com.zmn.oms.model.entity.conf.distribute.NonGridRobOrderConfig;
import com.zmn.oms.model.entity.conf.distribute.NonGridRobOrderConfigQuery;
import com.zmn.oms.model.entity.conf.distribute.RobOrderQuery;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.grab.NonGridGrabOrder;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.mongo.graborder.GrabOrder;
import com.zmn.oms.model.mongo.graborder.GrabOrderQuery;
import com.zmn.oms.model.query.grab.NonGridGrabOrderQuery;
import com.zmn.oms.services.interfaces.conf.distribute.NonGridRobOrderConfigService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.grab.NonGridGrabOrderService;
import com.zmn.oms.services.interfaces.graborder.GrabOrderService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkGrabBService;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsCustomWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：工单抢单状态
 *
 * @author liuying
 * @date 2021/07/19 11:47
 */
@Slf4j
@Service
public class OrderWorkGrabBServiceImpl implements OrderWorkGrabBService {

    private static final String GRAB_TAG = "抢单";
    private static final String REDIS_LOCK_KEY_FORMAT = "oms%s";

    @Resource
    private OrderWorkBService orderWorkBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Resource
    private GrabOrderService grabOrderService;
    @Resource
    private GrabOrderBService grabOrderBService;
    @Autowired
    private ZsCustomWorkBService zsCustomWorkBService;
    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;
    @Autowired
    private ZsMasterWorkBService zsMasterWorkBService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OrderProductService orderProductService;
    @Resource
    private ZmnMQSender zmnMQSender;
    @Resource
    private RedisManager redisManager;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;
    @Resource
    private OrderWorkEsBService orderWorkEsBService;
    @Resource
    private DistributeWeightListBService distributeWeightListBService;
    @Autowired
    private NonGridRobOrderConfigService nonGridRobOrderConfigService;
    @Autowired
    private NonGridGrabOrderService nonGridGrabOrderService;
    @Autowired
    private BaiduMapBService baiduMapBService;
    @Autowired
    private OrderTagService orderTagService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerListRemoteService engineerListRemoteService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerTakeConfigListRemoteService engineerTakeConfigListRemoteService;



   // @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    //private EngineerSkillListRemoteService engineerSkillListRemoteService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerServSkillListRemoteService engineerServSkillListRemoteService;



    //@Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    //private EngineerServiceAreaListRemoteService engineerServiceAreaListRemoteService;
    @Reference(version = com.zmn.gms.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private GridEditEngineerListRemoteService gridEditEngineerListRemoteService;
   // @Reference(version = com.zmn.gms.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
   // private ProductGroupListRemoteService productGroupListRemoteService;

    @Reference(version = com.zmn.gms.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerCooperateInfoListRemoteService engineerCooperateInfoListRemoteService;

    /**
     * 工程师抢单列表
     *
     * @param grabWorkQuery
     * @return
     */
    @Override
    public List<GrabOrderDTO> listGrabOrderByMasterInfo(GrabWorkQuery grabWorkQuery) throws OmsBaseException {
        GrabOrderQuery query = new GrabOrderQuery();

        // 获取工程师信息
        log.debug("listGrabOrderByMasterInfo#getEngineerDetailById 入参 [{}]",grabWorkQuery.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> engineerResponseDTO = engineerListRemoteService.getEngineerDetailById(grabWorkQuery.getMasterId());
        log.debug("【{}】查询工程师信息出参：【{}】", GRAB_TAG, JSON.toJSONString(engineerResponseDTO));
        if (!engineerResponseDTO.isSuccess() || Objects.isNull(engineerResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "获取工程师信息失败");
        }

        //BaseEngineerDRO baseEngineerDRO = engineerResponseDTO.getData();
        ForeignEngineerDetailInfoDRO baseEngineerDRO = engineerResponseDTO.getData();
        if (Objects.equals(baseEngineerDRO.getStopDistributeStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "你当前不在抢单状态");
        }
        boolean grabStatus = false;
        // 转正可以抢单
        if (Objects.equals(baseEngineerDRO.getOaStatus(),  EngineerOAStatusEnum.SIGN_CONTRACT.getCode())) {
            grabStatus = true;

        }
        // 试用期7天内可以抢单
        if (!grabStatus && Objects.equals(baseEngineerDRO.getOaStatus(), EngineerOAStatusEnum.PROBATION.getCode())) {
            long day = DateUtil.getTimespan(baseEngineerDRO.getCreateTime(), DateUtil.UNIT_DAY);
            if (day >= -7) {
                grabStatus = true;
            }
        }
        if (!grabStatus) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "你当前不在抢单状态");
        }

        query.setCityId(baseEngineerDRO.getCityId());
        query.setAgent(baseEngineerDRO.getCooperationType());
        query.setManageCompanyId(baseEngineerDRO.getSpCompanyId());
        query.setGridCompanyId(baseEngineerDRO.getSubCompanyId());

        // list dange
        // todo fubiao
        log.info("listGrabOrderByMasterInfo#listCooperateByEngineerId 入参 [{}]",grabWorkQuery.getMasterId());
        ResponseDTO<List<EngineerCooperateInfoDRO>> productGroup = engineerCooperateInfoListRemoteService.listCooperateByEngineerId(grabWorkQuery.getMasterId());
        log.info("listGrabOrderByMasterInfo#listCooperateByEngineerId 出参 [{}]",JSON.toJSONString(productGroup));
        log.debug("【{}】查询工程师业务类型出参：【{}】", GRAB_TAG, JSON.toJSONString(productGroup));
        if (!productGroup.isSuccess() || CollectionUtil.isNullOrEmpty(productGroup.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "抱歉，还没有合适的工单请您耐心等候");
        }
        List<Integer> bizTypeList = productGroup.getData().stream().map(EngineerCooperateInfoDRO::getBizType).distinct().collect(Collectors.toList());
        query.setBizTypeList(bizTypeList);

        OrderWork orderWork = new OrderWork();
        orderWork.setPlatWork(baseEngineerDRO.getPlat());
        orderWork.setCityId(query.getCityId());
        orderWork.setBizType(com.zmn.consts.GlobalConsts.BIZ_TYPE_C);
        orderWork.setManageCompanyId(baseEngineerDRO.getSpCompanyId());

        // 判断最大抢单数量
        this.processEngineerGrabNumber(grabWorkQuery.getMasterId(), orderWork);

        // 服务范围-网格
        ResponseDTO<List<EngineerGridDRO>> responseEngineerGrid = gridEditEngineerListRemoteService.listEngineerGrid(grabWorkQuery.getMasterId());
        log.debug("【{}】查询工程师网格绑定出参：【{}】", GRAB_TAG, JSON.toJSONString(responseEngineerGrid));
        List<EngineerGridDRO> gridDataList = responseEngineerGrid.getData();

        // 服务范围-工程师区域
        /*ResponseDTO<List<EngineerServiceAreaDRO>> engineerServiceAreaList = engineerServiceAreaListRemoteService.listEngineerServiceAreaByEngineerId(grabWorkQuery.getMasterId(), GlobalConsts.PLAT_MARK_ZMN);
        log.info("【{}】查询工程师服务范围出参：【{}】", GRAB_TAG, JSON.toJSONString(engineerServiceAreaList));
        List<EngineerServiceAreaDRO> serviceAreaListDataList = engineerServiceAreaList.getData();

        if (CollectionUtil.isNullOrEmpty(gridDataList) && CollectionUtil.isNullOrEmpty(serviceAreaListDataList)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "获取工程师服务区域失败");
        }*/

        if (CollectionUtil.isNotNullOrEmpty(gridDataList)) {
            List<Integer> gridIdList = gridDataList.stream().map(EngineerGridDRO::getGridId).collect(Collectors.toList());
            query.setGridList(gridIdList);
            // 设置城市
            //query.setCityId(gridDataList.get(0).getCityId());
        } /*else {
            query.setCityId(serviceAreaListDataList.get(0).getCityId());
        }*/

        // 抢单时间
        GrabConfigDTO grabConfigDTO = this.checkGrab(orderWork);
        if (!grabConfigDTO.getGrabStatus()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
        }
        if (!grabConfigDTO.getCheckGrab()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单时间为：" + grabConfigDTO.getNewestGrabTime());
        }

        /*if (CollectionUtil.isNotNullOrEmpty(serviceAreaListDataList)) {
            List<List<Point>> polygonList = Lists.newArrayList();
            List<Circle> circleList = Lists.newArrayList();
            List<Integer> countyIdList = Lists.newArrayList();
            List<Integer> cityIdList = Lists.newArrayList();
            List<Integer> streetIdList = Lists.newArrayList();

            serviceAreaListDataList.forEach(serviceArea -> {

                // 1：多边型地图（手绘），2：圆型地图，3：行政区域（当前等级下全部）为全部时map_data应该为空
                switch (serviceArea.getMapDataType()) {
                    case 1: // 1：多边型地图（手绘）
                        if (StringUtils.isBlank(serviceArea.getMapData())) {
                            return;
                        }
                        List<GeoPoint> mapDataList = JSON.parseArray(serviceArea.getMapData(), GeoPoint.class);
                        List<Point> pointList = Lists.newArrayListWithExpectedSize(mapDataList.size());
                        for (GeoPoint pot : mapDataList) {
                            Point point = new Point(pot.getLng(), pot.getLat());
                            pointList.add(point);
                        }
                        // 地图需要首尾相连
                        pointList.add(pointList.get(0));
                        polygonList.add(pointList);
                        return;
                    case 2: // 2：圆型地图
                        if (StringUtils.isBlank(serviceArea.getMapData())) {
                            return;
                        }
                        Point point = new Point(Double.valueOf(serviceArea.getLongitude()), Double.valueOf(serviceArea.getLatitude()));
                        Circle circle = new Circle(point, Double.valueOf(serviceArea.getMapData()));
                        circleList.add(circle);
                        return;
                    case 3: // 3：行政区域（当前等级下全部）为全部时map_data应该为空
                        if (Objects.equals(serviceArea.getLevel(), GlobalConsts.AREA_CITY)) {
                            // 城市
                            cityIdList.add(serviceArea.getCityId());
                        } else if (Objects.equals(serviceArea.getLevel(), GlobalConsts.AREA_COUNTY)) {
                            // 区县
                            countyIdList.add(serviceArea.getCountyId());
                        } else if (Objects.equals(serviceArea.getLevel(), GlobalConsts.AREA_STREET2)) {
                            // 街道
                            streetIdList.add(serviceArea.getStreetId());
                        }
                        return;
                }
            });

            query.setServiceAreaPolygonList(polygonList);
            query.setServiceAreaCircleList(circleList);
            query.setServiceAreaCityIdList(cityIdList.stream().distinct().collect(Collectors.toList()));
            query.setServiceAreaCountyIdList(countyIdList);
            query.setServiceAreaStreetIdList(streetIdList);

            // 设置城市
            query.setCityId(serviceAreaListDataList.get(0).getCityId());
        }*/

        // 查询工程师技能
        // todo fubiao
        log.info("listGrabOrderByMasterInfo#listServSkillByEngineerId 入参 [{}]",grabWorkQuery.getMasterId());
        ResponseDTO<List<EngineerServSkillDRO>> responseDTO = engineerServSkillListRemoteService.listServSkillByEngineerId(grabWorkQuery.getMasterId(), null);
        log.info("listGrabOrderByMasterInfo#listServSkillByEngineerId 出参 [{}]",JSON.toJSONString(responseDTO));
        log.debug("【{}】查询工程师技能出参：【{}】", GRAB_TAG, JSON.toJSONString(responseDTO));
        List<EngineerServSkillDRO> skillList = responseDTO.getData();
        if (CollectionUtil.isNullOrEmpty(skillList)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "抱歉，还没有合适的工单请您耐心等候");
        }
        List<Integer> servCategIdList = skillList.stream().map(EngineerServSkillDRO::getServCategId).collect(Collectors.toList());
        List<Integer> categIdList = skillList.stream().map(EngineerServSkillDRO::getCategId).collect(Collectors.toList());
        query.setServCategIdList(servCategIdList.stream().distinct().collect(Collectors.toList()));
        query.setCategIdList(categIdList.stream().distinct().collect(Collectors.toList()));
        // 查询抢单列表
        List<GrabOrder> grabOrderList = grabOrderBService.listGrabOrderByQuery(query);

        // 一级、二级分类集合（过滤使用）
        List<String> categStrList = skillList
                .stream()
                .map(dro -> String.format("%s_%s", dro.getServCategId(), dro.getCategId()))
                .collect(Collectors.toCollection(() -> new ArrayList<>(skillList.size())));

        List<GrabOrderDTO> resultList = Lists.newArrayListWithCapacity(grabOrderList.size());
        grabOrderList.forEach(item -> {
            // 过滤不符合分类条件的数据
            String categStr = String.format("%s_%s", item.getServCategId(), item.getCategId());
            if (!categStrList.contains(categStr)) {
                return;
            }
            GrabOrderDTO grabOrderDTO = GrabOrderDTO.builder()
                    .orderId(item.getOrderId())
                    .workId(item.getWorkId())
                    .productInfo(item.getProductInfo())
                    .address(String.join("", item.getCityName(), item.getCountyName(), DesensitizeUtil.desensitizedAddress(item.getStreet())))
                    .dutyTime(item.getDutyTime())
                    .grabEndTime(item.getGrabEndTime())
                    .grabVersion(item.getVersion())
                    .build();
            // 计算直线距离
            if (Objects.nonNull(grabWorkQuery.getLatitude())) {
                double distance = BaiduMapUtil.getDistance(grabWorkQuery.getLatitude(), grabWorkQuery.getLongitude(),
                        item.getLocation()[1], item.getLocation()[0]);
                grabOrderDTO.setDistance(distance);
            }

            // 标记为正常抢单
            grabOrderDTO.setGrabType(com.zmn.consts.GlobalConsts.NO);

            resultList.add(grabOrderDTO);
        });
        return resultList;
    }

    @Override
    public List<NonGridGrabOrderDRO> listNonGridGrabOrder(GrabQueryDIO grabQueryDIO) throws OmsBaseException {
        // 查询工程师信息
        log.debug("listGrabOrderByMasterInfo#getEngineerDetailById 入参 [{}]", grabQueryDIO.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> engineerResponseDTO = engineerListRemoteService.getEngineerDetailById(grabQueryDIO.getMasterId());
        log.debug("【{}】查询工程师信息出参：【{}】", GRAB_TAG, JSON.toJSONString(engineerResponseDTO));
        if (!engineerResponseDTO.isSuccess() || Objects.isNull(engineerResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "获取工程师信息失败");
        }

        ForeignEngineerDetailInfoDRO baseEngineerDRO = engineerResponseDTO.getData();

        // 查询无网格抢单配置
        NonGridRobOrderConfigQuery query = new NonGridRobOrderConfigQuery();
        query.setCityId(baseEngineerDRO.getCityId());
        List<NonGridRobOrderConfig> nonGridRobOrderConfigList = nonGridRobOrderConfigService.listNoGridRobConfigByQuery(query);
        log.debug("[{}]查询无网格抢单配置出参：【{}】", grabQueryDIO.getMasterId(), JSON.toJSONString(nonGridRobOrderConfigList));
        if (CollectionUtil.isNullOrEmpty(nonGridRobOrderConfigList)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
        }
        NonGridRobOrderConfig nonGridRobOrderConfig = nonGridRobOrderConfigList.get(0);
        // 抢单未开启、未选择公司类型、未选择工程师类型统统返回未开启抢单
        if (Objects.equals(nonGridRobOrderConfig.getRobOrderStatus(), GlobalConsts.NO)
                || StringUtil.isBlank(nonGridRobOrderConfig.getEngineerCompanyType())
                || Objects.isNull(nonGridRobOrderConfig.getEngineerType())) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
        }


        // 是否家修匠师傅
        boolean isJxj = Objects.equals(baseEngineerDRO.getSubCompanyId(), CompanyConsts.ZMN_JXJ_COMPANY_ID);
        if (isJxj) {
            // 如果公司类型未设置家修匠返回未开启
            if (!nonGridRobOrderConfig.getEngineerCompanyType().contains("2")) {
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
            }
        } else {
            // 如果公司类型未设置子公司返回未开启
            if (!nonGridRobOrderConfig.getEngineerCompanyType().contains("1")) {
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
            }
        }

        // 如果工程师类型不是全部
        if (!Objects.equals(nonGridRobOrderConfig.getEngineerType(), GlobalConsts.NONE)) {
            boolean isAgent = Objects.equals(baseEngineerDRO.getCooperationType(), GlobalConsts.NO);
            // 如果工程师是直营师傅判断抢单配置是否直营师傅
            if (isAgent) {
                if (!Objects.equals(nonGridRobOrderConfig.getEngineerType(), GlobalConsts.NO)) {
                    throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
                }
            } else {
                if (!Objects.equals(nonGridRobOrderConfig.getEngineerType(), GlobalConsts.YES)) {
                    throw new OmsBaseException(OmsErrorCodeConsts.ERROR_NON_GRAB_ORDER_CODE, "抢单未开启");
                }
            }
        }

        // 查询工程师当前抢单列表
        NonGridGrabOrderQuery nonGridGrabOrderQuery = new NonGridGrabOrderQuery();
        nonGridGrabOrderQuery.setMasterId(grabQueryDIO.getMasterId());
        nonGridGrabOrderQuery.setValidStatus(GlobalConsts.YES);
        log.debug("[{}]查询无网格抢单列表入参：【{}】", grabQueryDIO.getMasterId(), JSON.toJSONString(nonGridGrabOrderQuery));
        List<NonGridGrabOrder> nonGridGrabOrderList = nonGridGrabOrderService.listByQuery(nonGridGrabOrderQuery);
        log.debug("[{}]查询无网格抢单列表出参：【{}】", grabQueryDIO.getMasterId(), JSON.toJSONString(nonGridGrabOrderList));
        // 如果工程师列表为空直接返回
        if (CollectionUtil.isNullOrEmpty(nonGridGrabOrderList)) {
            return Lists.newArrayList();
        }

        // 结果
        List<NonGridGrabOrderDRO> result = Lists.newArrayListWithCapacity(nonGridGrabOrderList.size());

        // 如果师傅经纬度为空，使用派单时距离
        if (NumberUtil.isNullOrZero(grabQueryDIO.getLongitude()) || NumberUtil.isNullOrZero(grabQueryDIO.getLatitude())) {
            for (NonGridGrabOrder nonGridGrabOrder : nonGridGrabOrderList) {
                NonGridGrabOrderDRO dro = new NonGridGrabOrderDRO();
                dro.setOrderId(nonGridGrabOrder.getOrderId());
                dro.setWorkId(nonGridGrabOrder.getWorkId());
                dro.setGrabStatus(nonGridGrabOrder.getGrabStatus());
                dro.setProductInfo(nonGridGrabOrder.getProductInfo());
                dro.setDutyTime(nonGridGrabOrder.getDutyTime());
                dro.setDistance(nonGridGrabOrder.getDistance());
                if (Objects.equals(dro.getGrabStatus(), GlobalConsts.NO)) {
                    dro.setUnGrabReason("不满足无网格抢单：" + OrderDistributeConsts.getUnGridGrabReason(nonGridGrabOrder.getUnGrabReasonCode()));
                } else {
                    dro.setUnGrabReason(OrderDistributeConsts.getUnGridGrabReason(nonGridGrabOrder.getUnGrabReasonCode()));
                }
                result.add(dro);
            }
            return result;
        }

        for (NonGridGrabOrder e : nonGridGrabOrderList) {
            NonGridGrabOrderDRO dro = new NonGridGrabOrderDRO();
            dro.setOrderId(e.getOrderId());
            dro.setWorkId(e.getWorkId());
            dro.setProductInfo(e.getProductInfo());
            dro.setDutyTime(e.getDutyTime());
            // 重新计算抢单距离
            Double distance = baiduMapBService.getCornerDistance(grabQueryDIO.getLongitude(), grabQueryDIO.getLatitude(),
                    e.getLongitude(), e.getLatitude());
            // 如果订单可抢或者订单因为距离缘由不可抢，需要重新判断抢单距离
            if (NumberUtil.isNullOrZero(e.getUnGrabReasonCode()) ||
                    Objects.equals(e.getUnGrabReasonCode(), OrderDistributeConsts.UN_GRID_GRAB_MAX_DISTANCE_CODE)) {
                // 如果距离大于抢单距离，该订单不可抢。否则可抢
                if (distance.intValue() > (nonGridRobOrderConfig.getMaxRobDistance() * 1000)) {
                    e.setGrabStatus(GlobalConsts.NO);
                    e.setUnGrabReasonCode(OrderDistributeConsts.UN_GRID_GRAB_MAX_DISTANCE_CODE);
                } else {
                    e.setGrabStatus(GlobalConsts.YES);
                    e.setUnGrabReasonCode(GlobalConsts.NONE);
                }
            }
            dro.setDistance(distance.intValue());
            dro.setGrabStatus(e.getGrabStatus());
            if (Objects.equals(dro.getGrabStatus(), GlobalConsts.NO)) {
                dro.setUnGrabReason("不满足无网格抢单：" + OrderDistributeConsts.getUnGridGrabReason(e.getUnGrabReasonCode()));
            } else {
                dro.setUnGrabReason(OrderDistributeConsts.getUnGridGrabReason(e.getUnGrabReasonCode()));
            }
            result.add(dro);
        }

        // 重新排序，可抢在前
        result = result.stream().sorted(Comparator.comparing(NonGridGrabOrderDRO::getGrabStatus).reversed()).collect(Collectors.toList());

        return result;
    }

    /**
     * 处理抢单数量
     *
     * @param masterId
     * @throws OmsBaseException
     */
    private void processEngineerGrabNumber(Integer masterId, OrderWork orderWork) throws OmsBaseException {
        // todo fubiao
        log.info("processEngineerGrabNumber#getTakeConfig 入参 [{}] [{}]",masterId,orderWork.getWorkId());
        ResponseDTO<EngineerTakeConfigDRO> responseOrderConfig = engineerTakeConfigListRemoteService.getTakeConfig(masterId);
        log.info("processEngineerGrabNumber#getTakeConfig 出参 [{}]",JSON.toJSONString(responseOrderConfig));
        log.debug("【{}】查询工程师信息出参：【{}】", GRAB_TAG, JSON.toJSONString(responseOrderConfig));
        if (!responseOrderConfig.isSuccess() || Objects.isNull(responseOrderConfig.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "获取工程师接单配置失败");
        }
        String key = String.format(RedisKeyConsts.GRAB_ORDER_COUNT_KEY, masterId, DateUtil.dateFormatToString(DateUtil.getNow(), DateUtil.FORMAT_DATE2));
        String orderCount = redisManager.get(key);
        if (StringUtils.isNotBlank(orderCount) && Integer.parseInt(orderCount) >= responseOrderConfig.getData().getDayGrabOrderNum()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_MAX_GRAB_ORDER_CODE, "您今日抢单数量已达上限");
        }

        // 获取派单配置
        DistributeConfigDRO distributeConfigDRO = zsDistributeWorkBService.getDistributeConfig(orderWork);
        DistributeArgsDRO distributeArgsDRO = null;
        if (Objects.equals(distributeConfigDRO.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            distributeArgsDRO = distributeConfigDRO.getPlatDirectlyDistributeArgsDRO();
        } else {
            distributeArgsDRO = distributeConfigDRO.getDistributeArgsDRO();
        }

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("masterId", masterId));
        queryBuilder.must(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_REWORK));
        queryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));
        queryBuilder.must(QueryBuilders.termQuery("isTest", false));
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 100));
        int current = orderWorkEsBService.countByQuery(searchQuery).intValue();
        if (current >= distributeArgsDRO.getReworkLimit()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_MAX_GRAB_ORDER_CODE, "您的手头返修单数量已达上限");
        }
    }

    @Override
    public void grabOrderWork(GrabOrderWorkDTO grabOrderWorkDTO) throws OmsBaseException {
        // 查询工程师信息
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(grabOrderWorkDTO.getMasterId());
        log.debug("【{}】查询工程师信息出参：【{}】", GRAB_TAG, JSON.toJSONString(cacheEngineerByEngineerId));
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
        if (!cacheEngineerByEngineerId.isSuccess() || baseEngineerDRO == null) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_ENGINEER_INFO_CODE, "查询工程师信息失败");
        }

        // 分布式锁
        String key = "oms" + grabOrderWorkDTO.getWorkId().toString();
        DistributedLock lock = DistributedLockUtils.build(key, 5);
        if (!lock.tryLock()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "手慢了，工单已被其他工程师抢走");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(grabOrderWorkDTO.getOrderId(), grabOrderWorkDTO.getWorkId());
        // 处理最大抢单数量
        this.processEngineerGrabNumber(grabOrderWorkDTO.getMasterId(), orderWork);

        GrabOrder grabOrder = grabOrderService.findGrabOrderByWorkId(grabOrderWorkDTO.getWorkId());

        if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)
                || Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "抱歉，工单已被用户取消");
        }
        if (Objects.isNull(grabOrder)) {
            lock.unlock();
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "抢单时间已结束，下次请尽早抢单");
        }
        if (!Objects.equals(grabOrder.getVersion(), grabOrderWorkDTO.getGrabVersion())
                || Objects.equals(grabOrder.getGrabStatus(), GlobalConsts.YES)) {
            lock.unlock();
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "手慢了，工单已被其他工程师抢走");
        }

        // ***************派单操作*************
        try {
            String distributeKey = "grab-distribute-" + grabOrder.getWorkId();
            String message = JSON.toJSONString(grabOrderWorkDTO);
            zmnMQSender.send(MessageQueueTopicConstant.ZMN_TOPIC_OMS, OmsMqTagConsts.GRAB_ORDER_DISTRIBUTE_TAG, distributeKey, message);

            // 更新抢单状态
            grabOrderService.updateGrabStatus(grabOrderWorkDTO.getWorkId(), GlobalConsts.YES, grabOrderWorkDTO.getMasterId());

            String redisKey = String.format(RedisKeyConsts.GRAB_ORDER_COUNT_KEY, grabOrderWorkDTO.getMasterId(), DateUtil.dateFormatToString(DateUtil.getNow(), DateUtil.FORMAT_DATE2));
            LocalDateTime maxDateTime = LocalDate.now().atTime(LocalTime.MAX);
            redisManager.incr(redisKey);
            redisManager.expireAt(redisKey, maxDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void nonGridGrabOrderWork(GrabOrderWorkDTO grabOrderWorkDTO) throws OmsBaseException {
        // 分布式锁
        String key = String.format(RedisKeyConsts.OMS_NON_GRID_GRAB_ORDER_KEY, grabOrderWorkDTO.getWorkId());
        DistributedLock lock = DistributedLockUtils.build(key, 5);
        if (!lock.tryLock()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "手慢了，工单已被其他工程师抢走");
        }

        // 查询抢单列表
        NonGridGrabOrderQuery nonGridGrabOrderQuery = new NonGridGrabOrderQuery();
        nonGridGrabOrderQuery.setOrderId(grabOrderWorkDTO.getOrderId());
        nonGridGrabOrderQuery.setWorkId(grabOrderWorkDTO.getWorkId());
        nonGridGrabOrderQuery.setMasterId(grabOrderWorkDTO.getMasterId());
        nonGridGrabOrderQuery.setValidStatus(GlobalConsts.YES);
        List<NonGridGrabOrder> nonGridGrabOrderList = nonGridGrabOrderService.listByQuery(nonGridGrabOrderQuery);
        if (CollectionUtil.isNullOrEmpty(nonGridGrabOrderList)) {
            lock.unlock();
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "手慢了，工单已被其他工程师抢走");
        }

        // 修改有效状态
        NonGridGrabOrder nonGridGrabOrder = new NonGridGrabOrder();
        nonGridGrabOrder.setOrderId(grabOrderWorkDTO.getOrderId());
        nonGridGrabOrder.setWorkId(grabOrderWorkDTO.getWorkId());
        nonGridGrabOrder.setValidStatus(GlobalConsts.NO);
        nonGridGrabOrderService.updateByKey(nonGridGrabOrder);

        // 判断工单状态
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(grabOrderWorkDTO.getOrderId(), grabOrderWorkDTO.getWorkId());
        if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)
                || Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {
            lock.unlock();
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_GRAB_ORDER_CODE, "抱歉，工单已被用户取消");
        }

        // ***************派单操作*************
        String distributeKey = "grab-distribute-" + grabOrderWorkDTO.getWorkId();
        String message = JSON.toJSONString(grabOrderWorkDTO);
        zmnMQSender.send(MessageQueueTopicConstant.ZMN_TOPIC_OMS, OmsMqTagConsts.GRAB_ORDER_DISTRIBUTE_TAG, distributeKey, message);
        lock.unlock();
    }

    @Override
    public void grabDistributeOrder(GrabOrderWorkDTO grabOrderWorkDTO) throws OmsBaseException {
        // 查询工程师信息
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(grabOrderWorkDTO.getMasterId());
        log.debug("【{}】查询工程师信息出参：【{}】", GRAB_TAG, JSON.toJSONString(cacheEngineerByEngineerId));
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();

        // 记录派单路径
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(grabOrderWorkDTO.getOrderId(), grabOrderWorkDTO.getWorkId());

        // ***************派单操作*************
        OrderDistributeDTO distributeDTO = BeanMapper.map(grabOrderWorkDTO, OrderDistributeDTO.class);
        distributeDTO.setMasterName(baseEngineerDRO.getRealName());
        distributeDTO.setMasterPhone(baseEngineerDRO.getMobile());
        // 设置成已派单
        distributeDTO.setStatus(OrderStatusConsts.WORK_STATUS_DISTRIBUTE);
        if (Objects.equals(orderWork.getManageCompanyId(), GlobalConsts.NONE)) {
            distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        } else {
            distributeDTO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        }
        // 记录派单入口
        distributeDTO.setDistributeEntry(OrderDistributeConsts.DISTRIBUTE_ENTRY_APP);
        distributeDTO.setGrabType(GlobalConsts.YES);
        distributeDTO.setGrabWay(grabOrderWorkDTO.getGrabWay());
        distributeDTO.setOperateTime(DateUtil.getNow());
        zsCustomWorkBService.saveDistribute(distributeDTO);

        // ***************接单操作*************
        MasterTakeDTO masterTakeDTO = BeanMapper.map(distributeDTO, MasterTakeDTO.class);
        distributeDTO.setGrabType(GlobalConsts.YES);
        zsMasterWorkBService.updateMasterTake(masterTakeDTO);
    }

    /**
     * 更新抢单类型
     *
     * @param orderWorkGrabDTO
     */
    @Override
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_CHANGE_ASSIGNMENT)
    @Transactional
    public void saveGrabType(OrderWorkGrabDTO orderWorkGrabDTO) throws OmsBaseException {
        log.debug("【{}】抢单OrderWorkGrabDTO2：【{}】", GRAB_TAG, JSON.toJSONString(orderWorkGrabDTO));
        Objects.requireNonNull(orderWorkGrabDTO.getOrderId());
        Objects.requireNonNull(orderWorkGrabDTO.getWorkId());

        // 分布式锁
        String lockKey = String.format(REDIS_LOCK_KEY_FORMAT, orderWorkGrabDTO.getWorkId());
        DistributedLock lock = DistributedLockUtils.build(lockKey);
        if (!lock.tryLock()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_MODIFY_GRAB_ORDER_INFO_CODE, "订单信息发生变更");
        }

        try {
            if (Objects.equals(orderWorkGrabDTO.getGrabType(), GlobalConsts.YES)) {
                OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderWorkGrabDTO.getOrderId(), orderWorkGrabDTO.getWorkId());
                OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderWorkGrabDTO.getOrderId());
                List<OrderProduct> productList = orderProductService.listOrderProductByOrderId(orderWorkGrabDTO.getOrderId());
                GrabOrder grabOrder = this.getGrabOrder(orderWork, orderDetail, productList, orderWorkGrabDTO.getGrabEndTime());
                if (zsDistributeWorkBService.isGridDistribute(orderWork)) {
                    grabOrder.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
                } else {
                    grabOrder.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
                }
                grabOrder.setAgent(Optional.ofNullable(orderWorkGrabDTO.getAgent()).orElse(0));
                grabOrderBService.saveGrabOrderByOrderId(grabOrder);
            } else {
                grabOrderService.deleteGrabOrder(orderWorkGrabDTO.getWorkId());
            }

            // 更新状态
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderWorkGrabDTO.getOrderId());
            updateOrderWork.setWorkId(orderWorkGrabDTO.getWorkId());
            updateOrderWork.setGrabType(orderWorkGrabDTO.getGrabType());

            orderWorkBService.updateOrderWork(updateOrderWork);

            if (Objects.isNull(orderWorkGrabDTO.getAutoFlow())) {
                workFlowContextBService.asyncAutoFlow(updateOrderWork.getOrderId(),updateOrderWork.getWorkId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 抢单对象
     *
     * @param orderWork
     * @param orderDetail
     * @return
     */
    private GrabOrder getGrabOrder(OrderWork orderWork, OrderDetail orderDetail, List<OrderProduct> productList, Date grabEndTime) {
        GrabOrder grabOrder = new GrabOrder();
        grabOrder.setId(orderWork.getWorkId());
        grabOrder.setOrderId(orderWork.getOrderId());
        grabOrder.setWorkId(orderWork.getWorkId());

        grabOrder.setMasterId(GlobalConsts.NONE);
        grabOrder.setGrabStatus(GlobalConsts.NO);
        grabOrder.setAgent(GlobalConsts.NONE);
        grabOrder.setBizType(orderWork.getBizType());
        grabOrder.setManageCompanyId(orderWork.getManageCompanyId());

        grabOrder.setGridCompanyId(orderDetail.getGridCompanyId());
        grabOrder.setCityId(orderWork.getCityId());
        grabOrder.setCityName(orderDetail.getCityName());
        grabOrder.setCountyId(orderDetail.getCountyId());
        grabOrder.setCountyName(orderDetail.getCountyName());
        grabOrder.setStreetId(orderDetail.getStreetId());
        grabOrder.setStreet(orderDetail.getStreet());
        grabOrder.setGridId(orderDetail.getGridId());
        grabOrder.setLocation(new Double[]{orderDetail.getLongitude(), orderDetail.getLatitude()});

        grabOrder.setServCategId(orderWork.getServCategId());
        grabOrder.setCategId(orderDetail.getCategId());
        //grabOrder.setProductInfo(orderDetail.getProductInfo().substring(orderDetail.getProductInfo().indexOf("-") + 1));
        OrderProduct orderProduct = productList.get(0);
        grabOrder.setProductInfo(String.format("%s*%s", StringUtils.defaultString(orderProduct.getShowProductName(), orderProduct.getProductName()), orderProduct.getNumber()));

        grabOrder.setDutyTime(orderWork.getDutyTime());
        grabOrder.setCreateTime(orderWork.getCreateTime());
        grabOrder.setGrabEndTime(grabEndTime);
        grabOrder.setVersion(System.currentTimeMillis());

        return grabOrder;
    }

    /**
     * 抢单配置
     *
     * @param orderWork
     * @return GrabConfigDTO
     * @throws OmsBaseException
     */
    @Override
    public GrabConfigDTO grabConfig(OrderWork orderWork) throws OmsBaseException {
        RobOrderDRO dro = this.getRobOrderDRO(orderWork);
        if (Objects.equals(dro.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            return this.processGrabConfig(dro.getPlatDirectlyConfigDRO(), orderWork);
        } else {
            return this.processGrabConfig(dro.getCompanyConfigDRO(), orderWork);
        }
    }

    @Override
    public GrabConfigDTO checkGrab(OrderWork orderWork) throws OmsBaseException {
        RobOrderDRO dro = this.getRobOrderDRO(orderWork);
        if (Objects.equals(dro.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            return this.processGrabTime(dro.getPlatDirectlyConfigDRO());
        } else {
            return this.processGrabTime(dro.getCompanyConfigDRO());
        }
    }

    @Override
    public void removeFromGrabOrder(Long workId) throws OmsBaseException {
        Objects.requireNonNull(workId, "工单号不能为空");
        String lockKey = String.format(REDIS_LOCK_KEY_FORMAT, workId);
        DistributedLock lock = DistributedLockUtils.build(lockKey);
        if (!lock.tryLock()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_MODIFY_GRAB_ORDER_INFO_CODE, "订单信息发生变更");
        }

        try {
            GrabOrder grabOrder = grabOrderService.findGrabOrderByWorkId(workId);
            if (Objects.isNull(grabOrder)) {
                return;
            }

            if (Objects.equals(grabOrder.getGrabStatus(), GlobalConsts.NO)) {
                // 未被抢的订单，更新为指派模式
                OrderWork updateOrderWork = new OrderWork();
                updateOrderWork.setOrderId(workId);
                updateOrderWork.setWorkId(workId);
                updateOrderWork.setGrabType(GlobalConsts.NO);
                orderWorkBService.updateOrderWork(updateOrderWork);
            }

            grabOrderService.deleteGrabOrder(workId);

            workFlowContextBService.asyncAutoFlow(workId, workId);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 将订单从抢单池删除
     *
     * @param workId
     * @throws OmsBaseException
     */
    @Override
    public void deleteGrabOrderWithLock(Long workId) throws OmsBaseException {
        Objects.requireNonNull(workId, "工单号不能为空");
        String lockKey = String.format(REDIS_LOCK_KEY_FORMAT, workId);
        DistributedLock lock = DistributedLockUtils.build(lockKey);
        if (!lock.tryLock()) {
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_MODIFY_GRAB_ORDER_INFO_CODE, "订单信息发生变更");
        }
        try {
            grabOrderService.deleteGrabOrder(workId);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 获取抢单配置
     *
     * @param orderWork
     * @return
     * @throws OmsBaseException
     */
    private RobOrderDRO getRobOrderDRO(OrderWork orderWork) throws OmsBaseException {
        RobOrderQuery robOrderQuery = new RobOrderQuery();
        robOrderQuery.setCityId(orderWork.getCityId());
        robOrderQuery.setPlat(orderWork.getPlatWork());
        robOrderQuery.setBizType(orderWork.getBizType());
        DistributeConfigDRO distributeConfig = zsDistributeWorkBService.getDistributeConfig(orderWork);
        if (Objects.nonNull(distributeConfig) && Objects.equals(distributeConfig.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            robOrderQuery.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        } else {
            robOrderQuery.setCompanyId(orderWork.getManageCompanyId());
            robOrderQuery.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_SP);
        }
        log.info("【{}】获取抢单配置入参：【{}】", GRAB_TAG, JSON.toJSONString(robOrderQuery));
        RobOrderDRO robOrderConfig = distributeWeightListBService.findRobOrderConfig(robOrderQuery);
        log.info("【{}】获取抢单配置出参：【{}】", GRAB_TAG, JSON.toJSONString(robOrderConfig));
        if (Objects.isNull(robOrderConfig)) {
            throw new OmsBaseException("抢单未开启");
        }
        return robOrderConfig;
    }


    /**
     * 处理抢单配置
     *
     * @param robOrderConfigDRO
     * @param orderWork
     * @throws OmsBaseException
     */
    private GrabConfigDTO processGrabConfig(RobOrderConfigDRO robOrderConfigDRO, OrderWork orderWork) throws OmsBaseException {

        Date now = DateUtil.getNow();

        if (robOrderConfigDRO == null || !Objects.equals(robOrderConfigDRO.getRobOrderStatus(), com.zmn.consts.GlobalConsts.YES)) {
            throw new OmsBaseException("抢单未开启");
        }

        List<RobOrderRelationDRO> relationList = robOrderConfigDRO.getRobOrderRelationList();
        if (CollectionUtil.isNullOrEmpty(relationList)) {
            throw new OmsBaseException("抢单配置错误");
        }

        GrabConfigDTO grabConfigDTO = new GrabConfigDTO();
        boolean createTimeFlag = false;
        boolean dutyTimeFlag = false;
        boolean grabTimeFlag = false;
        boolean channelOneFlag = false;
        boolean channelTwoFlag = false;
        boolean servCategFlag = false;
        boolean showCategOneIdFlag = false;
        for (RobOrderRelationDRO dro : relationList) {

            if (StringUtil.isNotBlank(dro.getOrderTimeStart())) {
                // 判断下单时间是否满足
                createTimeFlag = DateTimeUtil.isBetween(orderWork.getReceiveTime(), dro.getOrderTimeStart(), dro.getOrderTimeEnd());
                if (!createTimeFlag) {
                    continue;
                }
            } else {
                createTimeFlag = true;
            }

            if (StringUtil.isNotBlank(dro.getAppointmentTimeStart())) {
                // 判断预约时间是否满足
                dutyTimeFlag = DateTimeUtil.isBetween(orderWork.getDutyTime(), dro.getAppointmentTimeStart(), dro.getAppointmentTimeEnd());
                if (!dutyTimeFlag) {
                    continue;
                }
            } else {
                dutyTimeFlag = true;
            }

            // 判断预约时间是否满足
            grabTimeFlag = DateTimeUtil.isBetween(now, dro.getRobOrderTimeStart(), dro.getRobOrderTimeEnd());
            if (!grabTimeFlag) {
                continue;
            }


            String channelOne = dro.getFirstLevelChannel();
            String channelTwo = dro.getSecondLevelChannel();

            // 剔除二级渠道是否满足
            if (StringUtil.isNotBlank(channelTwo)) {
                List<String> channelTwoList = Arrays.asList(channelTwo.split(","));
                if (channelTwoList.contains(String.valueOf(orderWork.getChannelId()))) {
                    channelTwoFlag = true;
                    break;
                }
            } else {
                // 剔除一级渠道是否满足
                if (StringUtil.isNotBlank(channelOne)) {
                    List<String> channelOneList = Arrays.asList(channelOne.split(","));
                    if (channelOneList.contains(String.valueOf(orderWork.getChannelTwoId()))) {
                        channelOneFlag = true;
                        break;
                    }
                }
            }

            // 判断服务分类是否满足
            List<RobOrderRelationProductDRO> productList = dro.getRobOrderRelationProductList();
            if (CollectionUtil.isNotNullOrEmpty(productList)) {
                for (RobOrderRelationProductDRO productDRO : productList) {
                    // 判断前台一级产品分类
                    String showCateOne = productDRO.getFirstLevelProduct();
                    String servCategId = productDRO.getServiceClassification();

                    if (Objects.equals(servCategId, String.valueOf(orderWork.getServCategId()))) {
                        if (StringUtil.isNotBlank(showCateOne)) {
                            List<String> showCateOneList = Arrays.asList(showCateOne.split(","));
                            if (showCateOneList.contains(String.valueOf(orderWork.getShowCategOneId()))) {
                                showCategOneIdFlag = true;
                                break;
                            }
                        } else {
                            servCategFlag = true;
                            break;
                        }
                    }
                }
            }

            grabConfigDTO.setAgent(Optional.ofNullable(dro.getEngineerType()).orElse(0));
            grabConfigDTO.setGrabTime(dro.getRobOrderTimeStart() + "~" + dro.getRobOrderTimeEnd());
            grabConfigDTO.setGrabEndTime(DateTimeUtil.getGrabEndTime(now, dro.getRobOrderTimeEnd()));
            break;
        }

        if (!createTimeFlag) {
            throw new OmsBaseException("下单时间不满足");
        }
        if (!dutyTimeFlag) {
            throw new OmsBaseException("预约时间不满足");
        }
        if (!grabTimeFlag) {
            throw new OmsBaseException("抢单时间不满足");
        }
        if (channelOneFlag) {
            throw new OmsBaseException("一级渠道不满足");
        }
        if (channelTwoFlag) {
            throw new OmsBaseException("二级渠道不满足");
        }
        if (servCategFlag) {
            throw new OmsBaseException("服务分类不满足");
        }
        if (showCategOneIdFlag) {
            throw new OmsBaseException("前台一级分类不满足");
        }

        return grabConfigDTO;
    }

    /**
     * 检查当前时间是否在抢单时间内，如果没有则返回获取最新派单时间
     *
     * @param robOrderConfigDRO
     * @return
     */
    private GrabConfigDTO processGrabTime(RobOrderConfigDRO robOrderConfigDRO) {
        GrabConfigDTO grabConfigDTO = new GrabConfigDTO();
        Date date = DateUtil.getNow();
        grabConfigDTO.setGrabStatus(true);
        if (robOrderConfigDRO == null || !Objects.equals(robOrderConfigDRO.getRobOrderStatus(), GlobalConsts.YES)) {
            grabConfigDTO.setCheckGrab(false);
            grabConfigDTO.setGrabStatus(false);
            return grabConfigDTO;
        }
        List<RobOrderRelationDRO> relationList = robOrderConfigDRO.getRobOrderRelationList();
        if (CollectionUtil.isNullOrEmpty(relationList)) {
            grabConfigDTO.setCheckGrab(false);
            grabConfigDTO.setGrabStatus(false);
            return grabConfigDTO;
        }
        List<String> grabTimeList = Lists.newArrayListWithCapacity(relationList.size());
        for (RobOrderRelationDRO dro : relationList) {
            if (Objects.nonNull(grabConfigDTO.getCheckGrab()) && grabConfigDTO.getCheckGrab()) {
                return grabConfigDTO;
            }
            grabConfigDTO.setCheckGrab(DateTimeUtil.isBetween(date, dro.getRobOrderTimeStart(), dro.getRobOrderTimeEnd()));
            grabTimeList.add(dro.getRobOrderTimeStart() + "~" + dro.getRobOrderTimeEnd());
        }
        grabConfigDTO.setNewestGrabTime(DateTimeUtil.getNewestGrabTime(date, grabTimeList));
        return grabConfigDTO;
    }
}
